home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / graphics / fractal / fraccntr.sit / Fractal Contours.c next >
Encoding:
C/C++ Source or Header  |  1991-07-16  |  38.3 KB  |  1,228 lines

  1. Path: asgb!bmcg!sdcc6!sdcc3!sdcsvax!dcdwest!ittatc!decvax!harpo!whuxlm!whuxl!houxm!mtuxo!mtunh!mtung!mtunf!ariel!vax135!cornell!uw-beaver!tektronix!teklds!hercules!keithr
  2. Subject: Fractal Contours Aztec C source.
  3. Organization: Tektronix, Inc.
  4.  
  5. This is the source to Fractal Contours that I promised to post.
  6. This program was written in Aztec C by Jim Cathey. Jim has moved
  7. onto other projects so he probably won't be releasing any improvements 
  8. in this program. 
  9.  
  10. Keith Rule
  11.  
  12. tektronix!teklds!keithr
  13.  
  14. ---------------------------- Cut Here ------------------------------
  15. #!/bin/sh
  16. # This is a shell archive, meaning:
  17. # 1. Remove everything above the #!/bin/sh line.
  18. # 2. Save the resulting text in a file.
  19. # 3. Execute the file with /bin/sh (not csh) to create the files:
  20. #       Makefile
  21. #       fractal.c
  22. #       fractal.h
  23. #       fractal.r
  24. #       fractal2.c
  25. # This archive created: Sun Aug 11 21:32:45 1985
  26. # By:   Keith Rule    tektronix!teklds!keithr (Tektronix, Inc.)
  27. export PATH; PATH=/bin:$PATH
  28. if test -f 'Makefile'
  29. then
  30.         echo shar: over-writing existing file "'Makefile'"
  31. fi
  32. cat << \SHAR_EOF > 'Makefile'
  33. #
  34. # Dependency Rules
  35. #
  36. #fractal.res: fractal.r
  37. #       rmaker fractal.r
  38. fractal.o: fractal.c fractal.h
  39.  
  40. fractal2.o: fractal2.c fractal.h
  41.  
  42. fractal: fractal.o fractal2.o
  43.         ln -m -o fractal sys:lib/sacroot.o fractal.o fractal2.o sys:lib/m.lib -lc
  44. SHAR_EOF
  45. if test -f 'fractal.c'
  46. then
  47.         echo shar: over-writing existing file "'fractal.c'"
  48. fi
  49. cat << \SHAR_EOF > 'fractal.c'
  50. /*
  51. **  Three-dimensional Fractal Contour Map generator.
  52. **  Program originally in MicroSoft BASIC for the Macintosh.
  53. **  Taken from July 1985 Creative Computing.
  54. **
  55. **  Used as an example BASIC-C comparison.
  56. */
  57.  
  58. #include <memory.h>
  59. #include <quickdraw.h>
  60. #include <font.h>
  61. #include <window.h>
  62. #include <osutil.h>
  63. #include <menu.h>
  64. #include <event.h>
  65. #include <textedit.h>
  66. #include <dialog.h>
  67. #include <desk.h>
  68. #include <control.h>
  69. #include <toolutil.h>
  70. #define watchCursor 4   /* Should be in TOOLUTIL.H but isn't.  JEC */
  71. #include <resource.h>
  72. #include <stdio.h>
  73.  
  74. #include "fractal.h"
  75.  
  76. GrafPtr screenport;             /* A port for the whole screen. */
  77. WindowPtr mywindow;             /* Our one window. */
  78. WindowRecord wrecord;           /* Storage for window record. */
  79. MenuHandle mymenus[LASTMENU + 1]; /* Our menus. */
  80. PicHandle thepicture;
  81. BitMap savepix;                 /* Storage for the update bitmap. */
  82.  
  83. EventRecord myevent;
  84. WindowPtr whichwindow;          /* Points to window of MouseDown. */
  85. int windowcode;                 /* What mouse was in when event posted. */
  86. Boolean userdone;               /* True when user wants to exit program. */
  87. int ispicture;          /* True if there is a Picture definition of the
  88.                            contour available. */
  89. int isbitmap;           /* True if there is a bitmap copy of the contour
  90.                            available.  Saves time in update events. */
  91. int usebitmap;          /* True if the bitmap should be used to update. */
  92.  
  93. main() {
  94.     setup();
  95.     maineventloop();
  96. }
  97.  
  98. /*############################   MainEventLoop  ########################*/  
  99.  
  100. maineventloop() {
  101.  
  102.     FlushEvents(everyEvent, 0);/* discard leftover events */
  103.  
  104. /* get next event, and handle it appropriately, until user QUITs */
  105.  
  106.     userdone = 0;
  107.     do {
  108.         SystemTask();           /* Handle desk accessories. */
  109.         if (GetNextEvent(everyEvent, &myevent)) {
  110.                                 /* get event; if for us... */
  111.             switch (myevent.what) {/* handle each kind of event */
  112.                 case mouseDown: /* find out what window the mouse went
  113.                                    down in, and where in it */
  114.                     windowcode = FindWindow(pass(myevent.where), &whichwindow);
  115.                     switch (windowcode) {
  116.                                 /* handle mouse-down for each place */
  117.                         case inSysWindow: 
  118.                                 /* handle the desk accessories */
  119.                             SystemClick(&myevent, whichwindow);
  120.                             break;/* insyswindow */
  121.                         case inMenuBar: /* handle the command */
  122.                             userdone = docommand(MenuSelect(&myevent.where));
  123.                             break;/* inmenubar */
  124.                         case inDrag: /* No Drag Region, treat as Content. */
  125.                         case inContent: 
  126.                                 /* includes inGrow if window inactive.
  127.                                    Activate window */
  128.                             if (whichwindow == mywindow)
  129.                                 /* make sure it's for mine */
  130.                                 if (whichwindow != FrontWindow())
  131.                                     SelectWindow(whichwindow);
  132.                                 /* make it active */
  133.                             break;
  134.                         case inGrow: /* No Grow Region */
  135.                             break;
  136.                         case inGoAway: 
  137.                                 /* we don't have a GoAway region */
  138.                             break;
  139.                     }
  140.                     break;      /* switch */
  141.  
  142.                 case keyDown: 
  143.                 case autoKey:   /* if command key, pass the char to
  144.                                    MenuKey */
  145.                     if ((myevent.modifiers & cmdKey) != 0)
  146.                         userdone = docommand(MenuKey((char) (myevent.message & charCodeMask)));
  147.                 case updateEvt: /* if it's for our window, update it */
  148.                     if ((WindowPtr) (myevent.message) == mywindow)
  149.                         updatewindow(mywindow);
  150.                                 /* redraw the window contents */
  151.                     break;
  152.                 case activateEvt: 
  153.                                 /* if for our window, set port as nec. */
  154.                     if ((WindowPtr) (myevent.message) == mywindow) {
  155.                                 /* my window */
  156.                         if (myevent.modifiers & 1) {
  157.                                 /* odd means an activate event */
  158.                             SetPort(mywindow);
  159.                                 /* activate evt: work in our own port */
  160.                                 DisableItem(mymenus[EDITMENU], 0);
  161.                                 EnableItem(mymenus[FILEMENU], 0);
  162.                                 EnableItem(mymenus[SETUPMENU], 0);
  163.                                 DrawMenuBar();
  164.                         }
  165.                         else {
  166.                                 SetPort(screenport);
  167.                                 /* deactivate evt: our port is gone; keep
  168.                                    port from dangling */
  169.                                 EnableItem(mymenus[EDITMENU], 0);
  170.                                 DisableItem(mymenus[FILEMENU], 0);
  171.                                 DisableItem(mymenus[SETUPMENU], 0);
  172.                                 DrawMenuBar();
  173.                         }
  174.                     } break;
  175.             }
  176.         }
  177.  
  178.     } while (userdone == 0);
  179. }
  180.  
  181. /*
  182. handle a command given through a menu selection
  183. ############################   DoCommand   ##############################
  184.  
  185.    We carry out the command indicated by mResult.
  186.    If it was Quit, we return true, else false.  Since the menu was
  187.    highlighted by MenuSelect, we must finish by unhighlighting it
  188.    to indicate we're done.
  189. */
  190. int     docommand(mresult)
  191. long    mresult;
  192. {
  193.     int     refnum;
  194.     int     themenu,
  195.             theitem;
  196.     char    name[255];
  197.     GrafPtr saveport;           /* for saving current port in when opening
  198.                                    a desk accessory */
  199.     int     returns;
  200.  
  201.     returns = 0;                /* assume Quit not selected */
  202.     themenu = HiWord(mresult);  /* get the menu selected */
  203.     theitem = LoWord(mresult);  /* ... and the item of that menu */
  204.     switch (themenu) {
  205.         case 0: 
  206.             break;              /* user made no selection; do nothing */
  207.  
  208.         case APPLEMENU: 
  209.  
  210.             if (theitem == 1)   /* Tell about FracCont */
  211.                 report();
  212.             else {              /* run a desk accessory; make sure port is
  213.                                    preserved */
  214.                 GetPort(&saveport);
  215.                 GetItem(mymenus[APPLEMENU], theitem, name);
  216.                                 /* get name */
  217.                 refnum = OpenDeskAcc(name);/* run the desk accessory */
  218.                 SetPort(saveport);
  219.             }
  220.             break;
  221.  
  222.         case FILEMENU: 
  223.             switch (theitem) {
  224.                 case ANOTHER:   /* New Surface */
  225.                         calcsurf(contlevl);
  226.                         InvalRect(&mywindow -> portRect);
  227.                         usebitmap = FALSE;
  228.                         break;
  229.                 case SAVEPAINT: /* Not yet. */
  230.                     break;
  231.                 case IQUIT: 
  232.                     returns = 1;/* Quit */
  233.                     break;
  234.             }                   /* FILEMENU case */
  235.             break;
  236.  
  237.         case SETUPMENU: 
  238.             switch (theitem) {
  239.                 case SETUP:     /* Setup */
  240.                     setupDlg();
  241.                     break;
  242.             }                   /* SETUPMENU case */
  243.  
  244.     }                           /* menu case */
  245.  
  246.     HiliteMenu(0);              /* turn off hilighting on the menu just
  247.                                    used */
  248.     return (returns);
  249. }                               /* DoCommand */
  250.  
  251. /*############################   Setup Dialog   ######################*/
  252.  
  253. TerrainBTN(ptr, oncontrl, offcontrl)
  254. DialogPtr ptr;
  255. int oncontrl, offcontrl;
  256. {
  257.         int itemtype;
  258.         ControlHandle item;
  259.         Rect itembox;
  260.  
  261.         GetDItem(ptr, offcontrl, &itemtype, &item, &itembox);
  262.         SetCtlVal(item, 0);     /* Turn off old Default Button. */
  263.         GetDItem(ptr, oncontrl, &itemtype, &item, &itembox);
  264.         SetCtlVal(item, 1);     /* Turn on Default Button. */
  265.         return oncontrl;
  266. }
  267.         
  268. setupDlg()                      /* Do the SETUP menu dialog. */
  269. {
  270.         int newtype;            /* Selected Contour type. */
  271.         int newlevel;           /* Selected Level of Detail. */
  272.         int userexit;
  273.         int doanother;          /* True if we need to recalc. */
  274.         int     itemhit;        /* Item # of punched button (or whatever) */
  275.         DialogPtr setupptr;
  276.         char asciibufr[10];
  277.         int itemtype;
  278.         ControlHandle item;
  279.         Rect itembox;
  280.         
  281.         newtype = conttype;     /* SETUPMTN, SETUPHIL, or SETUPWATR */
  282.         newlevel = contlevl;
  283.         doanother = FALSE;
  284.         
  285.         setupptr = GetNewDialog(STPDLGID, NULL, (long) -1);
  286.         TerrainBTN(setupptr, conttype, conttype);
  287.         asciibufr[1] = newlevel + '0';  /* Only good for 0..9, OK here. */
  288.         asciibufr[0] = 1;
  289.         GetDItem(setupptr, SETUPLEVL, &itemtype, &item, &itembox);
  290.         SetIText(item, asciibufr);
  291.         SelIText(setupptr, SETUPLEVL, 0, 100);  /* Hilite text field. */
  292.         userexit = FALSE;
  293.         do {
  294.                 ModalDialog(NULL, &itemhit);
  295.                                 /* carry out dialog; NIL => no FilterProc;
  296.                                    return item Hit when done */
  297.                 GetDItem(setupptr, SETUPLEVL, &itemtype, &item, &itembox);
  298.                 GetIText(item, asciibufr);      /* Get Level field */
  299.                 if (asciibufr[0] != 1)  /* Only good for 1..9, OK here. */
  300.                         newlevel = 100;
  301.                 else
  302.                         newlevel = asciibufr[1] - '0';
  303.                 if (newlevel < 1 || newlevel > MAXLEVEL)
  304.                         SelIText(setupptr, SETUPLEVL, 0, 100);  /* Hilite text field. */
  305.                 if (itemhit == SETUPMTN)
  306.                         newtype = TerrainBTN(setupptr, itemhit, newtype);
  307.                 if (itemhit == SETUPHIL)
  308.                         newtype = TerrainBTN(setupptr, itemhit, newtype);
  309.                 if (itemhit == SETUPWATR)
  310.                         newtype = TerrainBTN(setupptr, itemhit, newtype);
  311.                 if (itemhit == SETUPOK && ((newlevel > 0) & (newlevel <= MAXLEVEL))) {
  312.                         if (conttype != newtype || contlevl != newlevel) {
  313.                                 if (contlevl != newlevel)
  314.                                         doanother = TRUE;
  315.                                 InvalRect(&mywindow -> portRect);
  316.                                 usebitmap = FALSE;
  317.                         }
  318.                         contlevl = newlevel;
  319.                         conttype = newtype;
  320.                         userexit = TRUE;
  321.                 }
  322.                 if (itemhit == SETUPCAN)
  323.                         userexit = TRUE;
  324.         } while (!userexit);
  325.         DisposDialog(setupptr); /* release storage and remove dialog from
  326.                                            screen */
  327.         if (doanother)
  328.                 calcsurf(newlevel);     /* Removes dialog first. */
  329. }       /* Setup */
  330.  
  331.  
  332. /* 
  333. ############################   Report   #################################
  334. */
  335.  
  336. report()
  337. {
  338.     int     itemhit;            
  339.     DialogPtr reportptr;
  340.  
  341.     reportptr = GetNewDialog(INFOSCR1, NULL, (long) -1);
  342.                                 /* Get from Resource file; NIL => use heap
  343.                                    storage; -1 => make dlg frontmost */
  344.  
  345.     ModalDialog(NULL, &itemhit);
  346.                                 /* carry out dialog; NIL => no FilterProc;
  347.                                    return item Hit when done */
  348.     DisposDialog(reportptr);    /* release storage and remove dialog from
  349.                                    screen */
  350.     if (itemhit == INFOMORE) {
  351.         reportptr = GetNewDialog(INFOSCR2, NULL, (long) -1);
  352.         ModalDialog(NULL, &itemhit);
  353.         DisposDialog(reportptr);
  354.     }
  355. }
  356.  
  357.  
  358. /*
  359.  
  360. SetUps for handling memory
  361. ##########################   SetUpMemory   ############################
  362. */
  363.  
  364. setupmemory() {
  365.  
  366.  
  367. #define maxStackSize 8192       /* max size of stack; the heap gets the
  368.                                    rest */
  369.  
  370.     typedef long   *lomemptr;   /* a pointer to low memory locations */
  371.  
  372.     lomemptr nilptr;            /* will have value NIL */
  373.     lomemptr stackbaseptr;      /* points to current stack base */
  374.  
  375. /* 
  376.   If you define a GrowZone function to handle bad memory problems,
  377.   you should define it at the top level (not nested), and set it
  378.   here. We don't.
  379. */
  380. /*  SetGrowZone(&mygrowzone);     */
  381.  
  382. /* 
  383.   Place a longint -1 (an odd and therefore illegal address) in the
  384.   memory location that would be referenced by an accidentally-NULL
  385.   handle, so the error will be caught at handle-reference time (as
  386.   an Address error, ID=02) instead of later on.
  387. */
  388.  
  389.     nilptr = NULL;
  390.     *nilptr = -1;
  391.  
  392. /* 
  393.   If you needed to use an Application heap limit other than the
  394.   default (which allows 8K for the stack), you'd set it here,
  395.   possible using this technique of gX`licitly specifying the maximum
  396.   stack size and allocating the rest to the heap.  Should be
  397.   independent of memory size. */
  398.  
  399.     stackbaseptr = (lomemptr) 0x908;
  400.                                 /* CurStackBase from Tlasm/sysequ.text */
  401.     SetApplLimit((Ptr) (*stackbaseptr - maxStackSize));
  402.  
  403. /* 
  404.   Expand the application heap zone to its maximum size, without
  405.   purging any purgeable resources.  This saves memory compactions
  406.   and heap expansions later.
  407. */
  408.  
  409.     MaxApplZone();
  410.  
  411. /* 
  412.   get plenty of master pointers now; if we let the Memory Manager
  413.   allocate them as needed, they'd form non-relocatable islands in
  414.   the heap.
  415. */
  416.  
  417.     MoreMasters();
  418.     MoreMasters();
  419.  
  420. }                               /* SetUpMemory */
  421.  
  422. /*
  423. ############################   SetUpMenus   #############################
  424.     Once-only initialization for menus
  425.     We read in all menus from the resource file, and install them,
  426.     and all desk accessories (drivers).
  427. */
  428.  
  429. setupmenus() {
  430.     int     i;
  431.     for (i = 1; i <= LASTMENU; i++)/* get all my menus in */
  432.         mymenus[i] = GetMenu(i);/* use the fact that our menu ID's start
  433.                                    at 1 */
  434.     AddResMenu(mymenus[APPLEMENU], 'DRVR');
  435.                                 /* pull in all desk accessories */
  436.     for (i = 1; i <= LASTMENU; i++)
  437.         InsertMenu(mymenus[i], 0);/* insert menus; 0 => put at end */
  438.     DrawMenuBar();
  439. }
  440.  
  441. /*
  442.         
  443. body of SetUp
  444. Once-only initialization.
  445. ############################   SetUp   ##############################
  446.  
  447.    Initialize our program.  It seems best to handle:
  448.    Memory inits first, ToolBox inits second, then the program variables'
  449.    inits. Note that the order of inits is important; see "Using the
  450.    Dialog Manager" in the Dialog Mgr section.
  451.  
  452. */
  453.  
  454. setup() {
  455.  
  456.     char *ctop();
  457.         
  458.     setupmemory();              /*  init memory layout and protection */
  459.  
  460. /*  init QuickDraw, and everybody else */
  461.  
  462.     InitGraf(&thePort);
  463.     InitFonts();
  464.     InitWindows();
  465.     InitMenus();
  466.     TEInit();
  467.     InitDialogs(NULL);          /* NULL => no Restart proc; see Dialog Mgr
  468.                                    and System Error Handler */
  469.     InitCursor();
  470.  
  471. /* 
  472.   Init the system event mask, in case the previous program left
  473.   it in a bad state.  If you set it non-standard here, FIX IT
  474.   BEFORE EXITING, because the Finder (1.1g) does NOT set it.
  475. */
  476.     SetEventMask(everyEvent - keyUpMask);/* standard setting */
  477. /* 
  478.   Get the port which is the whole screen, to use when deactivating
  479.   our window.  This prevents the current grafPort pointer from
  480.   ever dangling.
  481. */
  482.     GetWMgrPort(&screenport);   /* get whole screen port that window mgr
  483.                                    uses */
  484.     SetPort(screenport);        /* and start off with it */
  485.  
  486. /* 
  487.   get window: use wRecord storage.  Port is set to that of the
  488.   new window.
  489.   GetNewWindow posts an update event for the new window,
  490.   so it will be redrawn right away.
  491. */
  492. #ifdef DEVELOP
  493.         OpenResFile(ctop(DEVELOP));
  494. #endif
  495.         mywindow = GetNewWindow(WINDOWID, &wrecord, (long) -1);
  496.                                 /* -1 => frontmost window */
  497.  
  498. /* pull in and set up our menus */
  499.         setupmenus();
  500.         CouldDialog(STPDLGID);  /* Preload the Setup Dialog. */
  501.  
  502.         conttype = DEFLTTYP;            /* Default style */
  503.         contlevl = DEFLTLEV;            /* Default Level */
  504.         isbitmap = FALSE;
  505.         /* Allocate the data array. */
  506.         points = NewPtr((long) XDIM*YDIM*(sizeof(int)));        /* Non-reloc, but so what. */
  507.         calcsurf(contlevl);             /* Do at least one first. */
  508. }
  509.  
  510. /*
  511.  
  512. Update the contents of the given window
  513. ############################   UpdateWindow   ##########################
  514.  
  515.    This is our response to receipt of an update event for myWindow.
  516.    Since the window is likely to be inactive, the current grafPort
  517.    will be elsewhere.  We must change it for drawing, yet leave it
  518.    as it was.
  519. */
  520.  
  521. updatewindow(awindow)
  522. WindowPtr awindow;
  523. {
  524.     GrafPtr saveport;           /* to save and restore the old port */
  525.  
  526.     BeginUpdate(awindow);       /* reset ClipRgn etc to only redraw what's
  527.                                    necessary. */
  528.  
  529.     GetPort(&saveport);         /* don't trash the port; we might be
  530.                                    updating an inactive window */
  531.     SetPort(awindow);           /* work in the specified window */
  532.  
  533.     drawwindow();               /* redraw contents of window */
  534.  
  535.     SetPort(saveport);          /* all nice and tidy as before */
  536.  
  537.     EndUpdate(awindow);
  538.  
  539. }                               /* UpdateWindow */
  540.  
  541. /* 
  542. Redraw my window
  543. ############################   DrawWindow   #############################
  544.  
  545.    We draw all the contents of our one window, myWindow.
  546. */
  547.  
  548. drawwindow()
  549. {
  550.         /* Possibly save the drawing contents in a picture.  This will allow
  551.            much faster update events than calling plotdata() repeatedly.
  552.            This is only to speed up Desk Accessory movement and the
  553.            re-painting after the Options Dialog is removed. */
  554.         CursHandle ticktock;
  555.  
  556.         ticktock = GetCursor(watchCursor);
  557.         if (ticktock)
  558.                 SetCursor(*ticktock);   /* Show watch (wait) */
  559.         if (usebitmap) {
  560.                 CopyBits(&savepix, &mywindow->portBits,
  561.                         &savepix.bounds, &mywindow->portRect,
  562.                         srcCopy, 0L);
  563.         }
  564.         else {
  565.                 if (isbitmap)
  566.                         DisposPtr(savepix.baseAddr);
  567.                 savepix.bounds.top = mywindow->portRect.top;
  568.                 savepix.bounds.bottom = mywindow->portRect.bottom;
  569.                 savepix.bounds.left = mywindow->portRect.left;
  570.                 savepix.bounds.right = mywindow->portRect.right;
  571.                 savepix.rowBytes = mywindow->portBits.rowBytes;
  572.                 savepix.baseAddr = NewPtr((long) savepix.rowBytes *
  573.                         (savepix.bounds.bottom - savepix.bounds.top));
  574.                 EraseRect(&mywindow->portRect);
  575.                 plotdata();
  576.                 CopyBits(&mywindow->portBits, &savepix,
  577.                         &mywindow->portRect, &savepix.bounds,
  578.                         srcCopy, 0L);
  579.                 isbitmap = usebitmap = TRUE;
  580.         }
  581. #ifdef not_defined
  582.         if (ispicture)
  583.                 KillPicture(thepicture);
  584.         thepicture = OpenPicture(&mywindow -> portRect);
  585.         ShowPen();      /* We want the picture shown while being drawn. */
  586.         EraseRect(&mywindow -> portRect);
  587.         plotdata();
  588.         HidePen();      /* Balance the ShowPen() above. */
  589.         ClosePicture();
  590.         ispicture = TRUE;
  591. #endif
  592.         InitCursor();
  593. }                               /* DrawWindow */
  594.  
  595. /*
  596.  *      The following routine was used while debugging and testing the program.
  597.  *      The routine is called just like "printf()", but the output is
  598.  *      directed to the printer port. Use -7 for the modem port.  The
  599.  *      port must already be opened.  Use MIXCROOT and do a 2> .b(a)out
  600.  *      to easily do this.
  601.  */
  602.  
  603. #ifdef DEBUG
  604. debug(fmt, arg)
  605. char *fmt;
  606. unsigned arg;
  607. {
  608.         int put();
  609.  
  610.         format(put, fmt, &arg);
  611. }
  612.  
  613. put(c)
  614. char c;
  615. {
  616.         long i;
  617.  
  618.         i = 1;
  619.         if (c=='\n')
  620.                 put('\r');
  621.         FSWrite(DEBUG, &i, &c);
  622.         if (c=='\n')
  623.                 for (i=2000; i; i--)
  624.                         ;
  625. }
  626. #endif
  627.  
  628. SHAR_EOF
  629. if test -f 'fractal.h'
  630. then
  631.         echo shar: over-writing existing file "'fractal.h'"
  632. fi
  633. cat << \SHAR_EOF > 'fractal.h'
  634. #define DEBUG -7                /* Includes debugging printer. */
  635.                                 /* Use -7 for modem port, -9 for printer. */
  636. #define DEVELOP "Frac:Fractal Contours" /* Resource file to open for
  637.                                            faster program development. */
  638.  
  639. #define LASTMENU 4              /* Number of menus. */
  640. #define APPLEMENU 1             /* Menu ID for Apple menu. */
  641. #define FILEMENU 2              /* Menu ID for File menu. */
  642. #define EDITMENU 3              /* Menu ID for Edit menu. */
  643. #define SETUPMENU 4             /* Menu ID for parameter setting. */
  644.  
  645. #define ANOTHER 1               /* Items in the File menu. */
  646.  /*-------*/
  647. #define SAVEPAINT 3
  648.  /*-------*/
  649. #define IQUIT 5
  650.  
  651. #define SETUP 1                 /* Items in the Setup menu. */
  652.  
  653. #define INFOSCR1 256            /* Resource ID for info dialog. */
  654. #define INFOSCR2 257            /*   " info #2 dialog. */
  655.  
  656. #define INFOOK 1                /* OK Button */
  657. #define INFOMORE 2              /* More Info Button */
  658.  
  659.  
  660. #define WINDOWID 260            /* Resource ID for my window. */
  661.  
  662.  
  663. /* Setup Dialog Stuff */
  664. #define STPDLGID 258            /* ID of our setup dialog in resource
  665.                                    fork. */
  666. #define SETUPOK 1               /* OK Button */
  667. #define SETUPCAN 2              /* CANCEL Button */
  668. #define SETUPLEVL 4             /* Level Text field */
  669. #define SETUPMTN 5              /* Mountain RadButton */
  670. #define SETUPHIL 6              /* Hills RadButton */
  671. #define SETUPWATR 7             /* Water RadButton */
  672.  
  673. #define MAXLEVEL 7              /* Maximum level of detail. */
  674. #define DEFLTLEV 4              /* Default level. */
  675. #define DEFLTTYP SETUPWATR      /* Default type. */
  676.  
  677. #define XDIM 129                /* 2^MAXLEVEL+1 */
  678. #define YDIM 65                 /* 2^(MAXLEVEL-1)+1 */
  679.  
  680. int (*points)[XDIM][YDIM];      /* The array of points to be subdivided. */
  681. int xmax, ymax;
  682. int conttype;                   /* Contour type. */
  683. int contlevl;                   /* Level of detail. */
  684.  
  685. SHAR_EOF
  686. if test -f 'fractal.r'
  687. then
  688.         echo shar: over-writing existing file "'fractal.r'"
  689. fi
  690. cat << \SHAR_EOF > 'fractal.r'
  691. *  Fractal.r -- Resource definition file for fractal contour map
  692. *               application.
  693.  
  694. * Tell RMAKER what to name the resource file
  695. !fractal
  696. APPLfrak
  697.  
  698. * Version data for the finder
  699. *    Our signature is "frak"
  700. *    res. ID = 0, by convention
  701. *    finder version data
  702. *    Note that the blank in 'STR ' is significant 3/8/85 WHJ
  703. TYPE frak = STR 
  704.   ,0
  705.   Frac 1.0 -- July 13, 1985
  706.  
  707. * Menus
  708. *   ID (4 => pre-load the resource; MUST NOT be purgeable!)
  709. *   menu title: an Apple symbol (in hex) for the Apple menu.
  710. *   menu entries, one per line. ( means it's initially disabled.
  711. *   An entry of  (-  means a disabled line of dashes.
  712. *   A trailing /Q means a command-key equivalent.
  713. *   blank line at end of menu.
  714. Type MENU
  715.   ,1(4)
  716. \14
  717.  About Fractal Contours
  718.  (-
  719.  
  720. Type MENU
  721.   ,2(4)
  722. File
  723.  New/N
  724.  (-
  725.  (Save as Paint FileI
  726.  (-
  727.  Quit/Q
  728.  
  729.    ,3(4)
  730. Edit
  731.  (Undo
  732.  (-
  733.  Cut/X
  734.  Copy/C
  735.  Paste/V
  736.  Clear
  737.  
  738.     ,4(4)
  739. Options
  740.  Contour ParametersI
  741.  
  742. * A Window template
  743. *   ID,(4 => pre-load the resource; 32 => purgeable)
  744. *    title
  745. *    BoundsRect (global Top, Left, Bottom, Right): where it appears on the
  746. screen
  747. *    Vis NoGo: it's visible, does not have close box
  748. *    ProcId: this is a standard type of window
  749. *    Refcon, for program's use.  Frac doesn't use it.
  750. Type WIND
  751.   ,260(36)
  752.   Fractal Contours
  753.   39 1 341 511
  754.   Visible NoGoAway
  755.   0
  756.   0
  757.  
  758. * Picture declarations.
  759. * For the Information screens.
  760. * Since RMaker doesn't know how to use these in
  761. * DITL's, we have to get in and patch it up with
  762. * ResEdit later.  Suck city!
  763.  
  764. * Type PICT = GNRL
  765. *     ,128
  766. *     .R
  767. * Draw:Scrapbook PICT -32753
  768. *
  769. *     ,129
  770. *     .R
  771. * Draw:Scrapbook PICT -32752
  772.  
  773.  
  774. * dialog box for About Fractal Contours
  775. *   ID (4 => pre-load the resource; MUST NOT be purgeable!)
  776. *   title
  777. *   BoundsRect(global: TLBR)
  778. *   Vis NoGo: it's visible, but has no close box
  779. *   ProcID: Window type is modal dialog
  780. *   RefCon: Unused user variable
  781. *   res. ID of item list
  782. Type DLOG
  783.   ,256(4)
  784.   Information Box
  785.   28 24 328 485
  786.   Visible NoGoAway
  787.   1
  788.   0
  789.   256
  790.  
  791.   ,257(4)
  792.   Information Box #2
  793.   28 24 328 485
  794.   Visible NoGoAway
  795.   1
  796.   0
  797.   257
  798.  
  799.   ,258(4)
  800.   Contour Parameters
  801.   44 109 221 397
  802.   Visible NoGoAway
  803.   0
  804.   0
  805.   258
  806.  
  807.  
  808.  
  809. * dialog item list for About Fractal
  810. *   ID (4 => pre-loaded; 32 => purgeable - it should always be purgeable.)
  811. *   # Items
  812. *   the first item:
  813. *      a Button you can select
  814. *      display rect (local coords)
  815. *      title
  816. Type DITL
  817.   ,256(36)
  818.   3
  819.   Button Enabled
  820.   97 14 118 99
  821. OK
  822.  
  823.   Button Enabled
  824.   96 114 118 201
  825. More Info 
  826.  
  827.   StatText Disabled
  828.   20 10 300 400
  829. Picture here
  830.  
  831.   ,257(36)
  832.   2
  833.   Button Enabled
  834.   273 205 294 290
  835. OK
  836.  
  837.   StatText Disabled
  838.   20 10 300 400
  839. Picture here
  840.  
  841. * dialog item list for Setup
  842. *   ID (4 => pre-loaded; 32 => purgeable - it should always be purgeable.)
  843.   ,258(36)
  844. 8
  845. *   1
  846. BtnItem Enabled
  847. 144 32 164 92
  848. OK
  849.  
  850. *   2
  851. BtnItem Enabled
  852. 144 184 164 244
  853. CANCEL
  854.  
  855. *   3
  856. StatText Disabled
  857. 32 16 48 128
  858. Level of Detail:
  859.  
  860. *   4
  861. EditText Disabled
  862. 32 128 49 162
  863.  
  864. *   5
  865. RadioItem Enabled
  866. 64 120 80 240
  867. Mountainous
  868.  
  869. *   6
  870. RadioItem Enabled
  871. 88 120 104 224
  872. Foothills
  873.  
  874. *   7
  875. RadioItem Enabled
  876. 112 120 128 264
  877. Foothills & Water
  878.  
  879. *   8
  880. StatText Disabled
  881. 64 16 83 116
  882. Contour type:
  883.  
  884. ***
  885. * Finder's Information follows.
  886. ***
  887.  
  888. Type BNDL
  889.    ,128(32)
  890.    FRAC 0
  891.    ICN# 0
  892.    0 128 1 129
  893.    FREF 0
  894.    0 128 1 129
  895.  
  896. * a File Reference
  897. *   ID, (32 => purgeable)
  898. *   "APPL" : a file of type APPL (FRAC itself) gets the following icon (a
  899. mountain);
  900. *       local icon ID; maps to global ID as specified in BNDL
  901. *   name of file that must accompany application if transferred; omit if none.
  902.   Type FREF
  903.    ,128(32)
  904.    APPL 0
  905.  
  906. * An icon list for the application icon (a mountain)
  907. *   ID (the application icon), (32 => purgeable)
  908. *   Data is Hex data (.H)
  909. *   the icon data: 32 lines of 8 hex chars each
  910. *   the icon mask: 32 lines of 8 hex chars each
  911. Type ICN# = GNRL
  912.  ,128(32)
  913. .H
  914. 0000 0000 0000 0000 0000 0000 0000 0000
  915. 0000 E000 0003 E000 0006 1000 0006 1000
  916. 000C 0800 003C 0C00 007C 7A00 0047 E300
  917. 01C6 1100 030C 1080 0278 10C0 06EE 3CE0
  918. 0583 47F0 1F00 C118 3303 820C 61BE 1C1E
  919. 4063 FFF7 7FFF 0000 0000 0000 0000 0000
  920. 0000 0000 0000 0000 0000 0000 0000 0000
  921. 0000 0000 0000 0000 0000 0000 0000 0000
  922. *
  923. 0000 0000 0000 0000 0000 0000 0000 0000
  924. 0000 E000 0003 E000 0007 F000 0007 F000
  925. 000F F800 003F FC00 007F FE00 007F FF00
  926. 01FF FF00 03FF FF80 03FF FFC0 07FF FFE0
  927. 07FF FFF0 1FFF FFF8 3FFF FFFC 7FFF FFFE
  928. 7FFF FFFF 7FFF 0000 0000 0000 0000 0000
  929. 0000 0000 0000 0000 0000 0000 0000 0000
  930. 0000 0000 0000 0000 0000 0000 0000 0000
  931.  
  932. ****    end of information for the finder                          ****
  933. ***********************************************************************
  934.  
  935.  
  936. *INCLUDE fractal.code
  937.  
  938. SHAR_EOF
  939. if test -f 'fractal2.c'
  940. then
  941.         echo shar: over-writing existing file "'fractal2.c'"
  942. fi
  943. cat << \SHAR_EOF > 'fractal2.c'
  944.  
  945. /*
  946. ' 3-Dimensional Fractal surface generating program
  947. ' From July '85 Creative Computing.
  948. */
  949.  
  950. #include <quickdraw.h>
  951. #include <toolutil.h>
  952. #define watchCursor 4   /* Should be in TOOLUTIL.H but isn't.  JEC */
  953. double ran();           /* Should be in MATH.H but isn't.  JEC */
  954.  
  955. #include "fractal.h"
  956.  
  957. #define TRUE (-1)
  958. #define FALSE 0
  959.  
  960. int linestart;          /* True at the first of the line. */
  961. int color;              /* True when plotting land, else false. */
  962.  
  963. calcsurf(level)
  964. int level;
  965. {
  966.         int i, j, length, incrby, sk;
  967.         float power;
  968.         CursHandle ticktock;
  969.         
  970.         if (!points)
  971.                 return;
  972.         ticktock = GetCursor(watchCursor);
  973.         if (ticktock)
  974.                 SetCursor(*ticktock);   /* Show watch (wait) */
  975.  
  976.         xmax = 1 << level;
  977.         ymax = xmax/2;
  978.         for (i=0; i<=xmax; i++)         /* Clear the Array.  Use i & incrby as temps. */
  979.                 for (incrby=0; incrby<=ymax; incrby++)
  980.                         (*points)[i][incrby] = 0;
  981.  
  982.         for (i=1; i<= level; i++) {
  983.                 for (power=1.0, j=0; j<i; j++)
  984.                         power *= 1.8;
  985.                 length = 10000/power;           /* = 10000/(1.8^i) */
  986.                 incrby = xmax/(1 << i);   /* # of line segments in a side of the triangle. */
  987.                 sk = incrby * 2;
  988.                 calcxs(length, incrby, sk);
  989.                 calcys(length, incrby, sk);
  990.                 calcdiags(length, incrby, sk);
  991.         }
  992.         InitCursor();           /* Put back the arrow. */
  993. }
  994.  
  995. calcxs(len, incr, sk)   /* Assign heights along x in array. */
  996. int len;
  997. register int incr, sk;
  998. {
  999.         register int y, x;
  1000.         int d1, d2;
  1001.  
  1002.         for (y=0; y < xmax; y += sk) {
  1003.                 for (x = incr+y; x <= xmax; x += sk) {
  1004.                         d1 = getdata(x-incr, y);
  1005.                         d2 = getdata(x+incr, y);
  1006.                         stuffdata(((d1+d2)>>1) + (int)(ran()*(len>>1)) - (len>>2), x, y);
  1007.                 }
  1008.         }
  1009. }
  1010.  
  1011. calcys(len, incr, sk)   /* Assign heights along y in array. */
  1012. int len;
  1013. register int incr, sk;
  1014. {
  1015.         register int y, x;
  1016.         int d1, d2;
  1017.         
  1018.         for (x=xmax; x >= 1; x -= sk)
  1019.                 for (y = incr; y <= x; y += sk) {
  1020.                         d1 = getdata(x, y+incr);
  1021.                         d2 = getdata(x, y-incr);
  1022.                         stuffdata(((d1+d2)>>1) + (int)(ran()*(len>>1)) - (len>>2), x, y);
  1023.                 }
  1024. }
  1025.  
  1026. calcdiags(len, incr, sk)        /* Assign heights along diagonal in array. */
  1027. int len;
  1028. register int incr, sk;
  1029. {
  1030.         register int y, x;
  1031.         int d1, d2;
  1032.         
  1033.         for (x=0; x < xmax; x += sk)
  1034.                 for (y = incr; y <= xmax-x; y += sk) {
  1035.                         d1 = getdata(x+y-incr, y-incr);
  1036.                         d2 = getdata(x+y+incr, y+incr);
  1037.                         stuffdata(((d1+d2)>>1) + (int)(ran()*(len>>1)) - (len>>2), x+y, y);
  1038.                 }
  1039. }
  1040.  
  1041. getdata(x, y)
  1042. register int x, y;
  1043. {
  1044.         if (y <= ymax)
  1045.                 return (*points)[x][y];
  1046.         else
  1047.                 return (*points)[xmax-x][xmax+1-y];
  1048. }
  1049.  
  1050. stuffdata(d, x, y)
  1051. register int d, x, y;
  1052. {
  1053.         if (y <= ymax)
  1054.                 (*points)[x][y] = d;
  1055.         else
  1056.                 (*points)[xmax-x][xmax+1-y] = d;
  1057. }
  1058.  
  1059.  
  1060. /*
  1061. **      Our window is already open at this point, and it is cleared,
  1062. **      all we have to do now is fill it.
  1063. **      Draw the 2D projection of the triangular database on the screen.
  1064. */
  1065.  
  1066. plotdata()
  1067. {
  1068.         register int xindex, yindex;
  1069.         
  1070.         if (!points)
  1071.                 return;
  1072.         color = TRUE;           /* On land to start. */
  1073.  
  1074.         for (xindex=0; xindex<=xmax; xindex++) {        /* Plot along X axis. */
  1075.                 linestart = TRUE;
  1076.                 for (yindex=0; yindex<=xindex; yindex++)
  1077.                         doplot(xindex, yindex);
  1078.         }
  1079.         for (yindex=0; yindex<=xmax; yindex++) {        /* Plot along Y axis. */
  1080.                 linestart = TRUE;
  1081.                 for (xindex=yindex; xindex<=xmax; xindex++)
  1082.                         doplot(xindex, yindex);
  1083.         }
  1084.         for (xindex=0; xindex<=xmax; xindex++) {        /* Plot along the diagonal. */
  1085.                 linestart = TRUE;
  1086.                 for (yindex=0; yindex<=xmax-xindex; yindex++)
  1087.                         doplot(xindex+yindex, yindex);
  1088.         }
  1089. }
  1090.  
  1091. doplot(xindex, yindex)
  1092. int xindex, yindex;
  1093. {
  1094.         int xcoord, ycoord, zcoord;
  1095.         zcoord = getdata(xindex, yindex);
  1096.         ycoord = scaler(yindex, 10000, xmax);
  1097.         xcoord = scaler(xindex, 10000, xmax) - ycoord/2;
  1098.         if (conttype == SETUPWATR)
  1099.                 sealevel(&xcoord, &ycoord, &zcoord);
  1100.         plotto(xcoord, ycoord, zcoord);
  1101. }
  1102.  
  1103. sealevel(newx, newy, newz)
  1104. int *newx, *newy, *newz;
  1105. {
  1106.         static int oldx, oldy, oldz;    /* The starting point for the next call. */
  1107.         int waterx, watery, waterz;     /* Where the vector hits the waterline. */
  1108.         float scratch;
  1109.         
  1110.         if (linestart) {        /* If at the beginning of the line */
  1111.                 if ((oldz = *newz) < 0) {               /* and if we're underwater. */
  1112.                         color = FALSE;
  1113.                         *newz = 0;              /* Clip to the waterline. */
  1114.                 }
  1115.                 else
  1116.                         color = TRUE;   /* Otherwise we're on land from the start. */
  1117.         }
  1118.         else {          /* Else we're in the middle of a line and ... */
  1119.                 if (oldz > 0 && *newz > 0) {    /* start & end points both above water.. */
  1120.                         oldz = *newz;
  1121.                 }
  1122.                 else if (oldz < 0 && *newz < 0) {       /* start & end points both under water... */
  1123.                         oldz = *newz;
  1124.                         *newz = 0;              /* Clip at the waterline */
  1125.                 }
  1126.                 else {  /* We're now crossing the waterline, */
  1127.                         /* so calculate the exact point where it dives under. */
  1128.                         scratch = (float) (*newz)/(*newz-oldz); /* Proportion of the line that's */
  1129.                         waterx = (int) ((oldx - *newx)*scratch) + *newx;        /* below the water. */
  1130.                         watery = (int) ((oldy - *newy)*scratch) + *newy;
  1131.                         waterz = 0;
  1132.  
  1133.                         plotto(waterx, watery, waterz);         /* Draw to the waterline first. */
  1134.                         /* The plot from the waterline to the endpoint in the new color 
  1135.                            is done elsewhere. */
  1136.                         if (*newz > 0) {        /* Emerging from the water. */
  1137.                                 color = TRUE;   /* Set new color to 'land'. */
  1138.                                 oldz = *newz;
  1139.                         }
  1140.                         else {          /* Diving into the water. */
  1141.                                 color = FALSE;  /* Set new color to 'sea'. */
  1142.                                 oldz = *newz;
  1143.                                 *newz = 0;
  1144.                         }
  1145.                 }
  1146.         }
  1147.         oldx = *newx;   /* Save the real endpoint of the vector */
  1148.         oldy = *newy;   /* to use as the start of the next call. */
  1149.                         /* (Z taken care of individually above). */
  1150. }
  1151.  
  1152. scaler(base, numer, denom)      /* Computes base*numer/denom with long intermediate.
  1153. */
  1154. register int base, numer, denom;
  1155. {
  1156.         register long temp;
  1157.         temp = (long) base * (long) numer;
  1158.         temp /= (long) denom;
  1159.         return (int) temp;
  1160. }
  1161.  
  1162. plotto(x, y, z)         /* Convert 3-D line to a 2-D line and plot it. */
  1163. int x, y, z;
  1164. {
  1165.         rotate(&x, &y);         /* Rotate 30 deg. towards Y in the XY plane */
  1166.         tiltdown(&x, &z);       /* Tip 36 deg. down in the ZX plane */
  1167.         x /= 25;                /* Scale 10K to 400. */
  1168.         y /= 25;
  1169.         z /= 25;
  1170.         drawline(y, z);         /* Show the YZ planar projection. */
  1171. }
  1172.  
  1173. rotate(x, y)            /* Rotate XY plane 30 deg positive. */
  1174. int *x, *y;
  1175. {
  1176.         cordic(x, y, 5, 17);
  1177. }
  1178.  
  1179. tiltdown(x, z)          /* Rotate XZ plane 36 deg negative (+?). */
  1180. int *x, *z;
  1181. {
  1182.         cordic(x, z, 5, (conttype == SETUPMTN) ? 20 : -20);
  1183. }
  1184.  
  1185. drawline(x, y)          /* Draw either a line from the last endpoint */
  1186. int x, y;               /* to the given point, or only a point at x,y. */
  1187. {
  1188.         static int lastx, lasty;
  1189.         x += x/10 + 10; /* Quick x1.1 + tiny offset. */
  1190.         if (conttype == SETUPMTN)
  1191.                 y = 220 - y;    /* Move the baseline for mountains. */
  1192.         else
  1193.                 y = 80 - y;
  1194.         if (linestart || !color)        /* Only a point then. */
  1195.                 MoveTo(x, y);
  1196.         LineTo(x, y);
  1197.         lastx = x;
  1198.         lasty = y;
  1199.         linestart = FALSE;      /* Stuck in the middle with you... */
  1200. }
  1201.  
  1202. cordic(x, y, scale, count)      /* Spin XY vector 'count' steps to the left using */
  1203. int *x, *y;                     /* CORDIC algorithm with a shift factor of 'scale'. */
  1204. register int scale, count;      /* Rotates atan(1/(2^scale)) degrees/step. */
  1205.                                 /* (Scale of 5 is 1.79 deg/step;  4 = 3.57 d/s...) */
  1206.                                 /* *x & *y should be large for accuracy. */
  1207. {
  1208.         register int tempx, tempy;
  1209.         tempx = *x;
  1210.         tempy = *y;
  1211.         if (count>0)    /* Positive count is CCW (left) */
  1212.                 for (; count; count--) {
  1213.                         tempx -= (tempy>>scale);
  1214.                         tempy += (tempx>>scale);
  1215.                 }
  1216.         else            /* Negative is CW (right) */
  1217.                 for (; count; count++) {
  1218.                         tempx += (tempy>>scale);
  1219.                         tempy -= (tempx>>scale);
  1220.                 }
  1221.         *x = tempx;
  1222.         *y = tempy;
  1223. }
  1224.  
  1225. SHAR_EOF
  1226. #       End of shell archive
  1227. exit 0
  1228.